---
const { id, filePath } = Astro.props;
import fs from 'node:fs/promises';
import { existsSync } from 'fs';
import yaml from 'js-yaml';
import JSONSchemaViewer from '@components/SchemaExplorer/JSONSchemaViewer';
import AvroSchemaViewer from '@components/SchemaExplorer/AvroSchemaViewer';
import Admonition from '../Admonition';
import { getMDXComponentsByName } from '@utils/markdown';
import { getAbsoluteFilePathForAstroFile, resolveProjectPath, isAvroSchema } from '@utils/files';

let schemas = [];

try {
  const absoluteFilePath = resolveProjectPath(filePath);
  const file = await fs.readFile(absoluteFilePath, 'utf-8');
  const schemaViewers = getMDXComponentsByName(file, 'SchemaViewer');

  // Loop around all the possible SchemaViewers in the file.
  const getAllComponents = schemaViewers.map(async (schemaViewerProps: any, index: number) => {
    const schemaPath = getAbsoluteFilePathForAstroFile(filePath, schemaViewerProps.file);
    const exists = existsSync(schemaPath);
    let schema;
    let render = true;
    let isAvro = false;

    if (exists) {
      // Check if this is an Avro schema file
      isAvro = isAvroSchema(schemaPath);

      // Load the schema for the component
      schema = await fs.readFile(schemaPath, 'utf-8');

      if (schemaPath.endsWith('.yml') || schemaPath.endsWith('.yaml')) {
        schema = yaml.load(schema);
      } else {
        schema = JSON.parse(schema);

        // For non-Avro schemas, let JSON schema control if the component should be rendered
        if (!isAvro && schema['x-eventcatalog-render-schema-viewer'] !== undefined) {
          render = schema['x-eventcatalog-render-schema-viewer'];
        }
      }
    }

    return {
      id: schemaViewerProps.id || id,
      exists,
      schema,
      schemaPath,
      isAvroSchema: isAvro,
      ...schemaViewerProps,
      render,
      index,
    };
  });

  schemas = await Promise.all(getAllComponents);
} catch (error) {
  console.log('Failed to process schemas');
  console.log(error);
}
---

<section class="space-y-4">
  {
    schemas.length > 0 &&
      schemas.map((schema) => {
        if (!schema.render) return null;
        return (
          <div>
            {schema.exists && (
              <div
                id={`${schema.id}-${schema.file}-SchemaViewer-client`}
                class="not-prose my-4"
                data-expand={schema.expand ? 'true' : 'false'}
                data-search={schema.search !== false ? 'true' : 'false'}
              >
                {schema.title && <h2 class="text-2xl font-bold mb-2 !mt-0">{schema.title}</h2>}

                {/* Render AvroSchemaViewer for Avro schemas */}
                {schema.isAvroSchema ? (
                  <AvroSchemaViewer
                    client:load
                    schema={schema.schema}
                    maxHeight={schema.maxHeight}
                    expand={schema.expand}
                    search={schema.search}
                    showRequired={schema.showRequired}
                  />
                ) : (
                  <JSONSchemaViewer
                    client:load
                    schema={schema.schema}
                    maxHeight={schema.maxHeight}
                    expand={schema.expand}
                    search={schema.search}
                  />
                )}
              </div>
            )}

            {/* User has tried to load the schema, but it was not found on file system */}
            {!schema.exists && (
              <Admonition type="warning">
                <div>
                  <span class="block font-bold">{`<SchemaViewer/>`} failed to load</span>
                  <span class="block">Tried to load schema from {schema.schemaPath}, but no schema can be found</span>
                </div>
              </Admonition>
            )}
          </div>
        );
      })
  }
</section>

<script is:inline define:vars={{ schemas }}>
  // Can we move the SchemaViewerClient to another container? example container with the id "my-schema-viewer-container"
  // and then we can move the SchemaViewerClient to that container?

  function moveSchemaViewerToPortal(schema) {
    const portalId = `${schema.id}-${schema.file}-SchemaViewer-portal`;
    const schemaViewerContainer = document.getElementById(portalId);
    const schemaViewerClient = document.getElementById(`${schema.id}-${schema.file}-SchemaViewer-client`);

    if (schemaViewerContainer && schemaViewerClient) {
      // Get attributes from the portal
      const expand = schemaViewerContainer.getAttribute('data-expand') === 'true';
      const maxHeight = schemaViewerContainer.getAttribute('data-max-height');
      const search = schemaViewerContainer.getAttribute('data-search');

      // Set the expand attribute on the schema viewer client
      if (expand) {
        schemaViewerClient.setAttribute('data-expand', 'true');
      }

      // Set the search attribute on the schema viewer client
      if (search) {
        schemaViewerClient.setAttribute('data-search', search);
      }

      // Set the maxHeight on the schema viewer element
      if (maxHeight) {
        const schemaViewerElement = schemaViewerClient.querySelector('.schema-viewer');
        if (schemaViewerElement) {
          schemaViewerElement.style.maxHeight = `${maxHeight}px`;
        }
      }

      schemaViewerContainer.appendChild(schemaViewerClient);
    }
  }

  // on DOM ready, move the SchemaViewerClient to the portal
  document.addEventListener('DOMContentLoaded', () => {
    schemas.forEach(moveSchemaViewerToPortal);
  });

  // on DOM ready, move the SchemaViewerClient to the portal
  document.addEventListener('astro:page-load', () => {
    schemas.forEach(moveSchemaViewerToPortal);
  });
</script>
